/**
 * 结合 WebConfig 和流量超市的配置
 * 整合成统一的主体信息
 */
import { failed } from '@gnlab/utils'
import { useRefValue } from '@gnlab/utils/env-react'
import {
  type AppsCorpInfo,
  type AppsCorpDetail,
  useAppsCorps,
  updateAppsCorp,
  addAppsCorp,
  getAppsCorpDetail,
} from './apps-corps'
import { type QywxAPIConfig, useAPIConfigs, updateApiConfig } from './qywx-api-configs'

export * from './qywx-api-configs'
export * from './apps-corps'

export interface CorpInfo {
  corpId: string
  corpName: string | null // 为 null 代表流量超市里没有此主体
}

export interface CorpDetail {
  corpId: string
  secret: string
  corpIdOrigin: string
  appsInfo: Omit<AppsCorpDetail, 'corpId' | 'secret'> | null // 为 null 代表流量超市里没有此主体
}

/**
 * 维护整合后的主体列表
 */
export function useCorps() {
  const { apiConfigs, loadApiConfigs } = useAPIConfigs()
  const { appsCorps, loadAppsCorps } = useAppsCorps()

  const [loading, setLoading] = useState(false)
  const load = useCallback(
    async (initial = false) => {
      setLoading(true)
      // 仅初始化时刷新 apiConfigs，因为后续更新时 apiConfigs 会自行刷新数据
      await Promise.all([loadAppsCorps(), initial ? loadApiConfigs() : Promise.resolve()])
      setLoading(false)
    },
    [loadApiConfigs, loadAppsCorps],
  )
  useEffect(() => void load(true), [load])

  // 整合数据
  // 以 apiConfig 作为核心；只在 apps 里存在的主体不显示出来（因为没有对应的 apiConfig，即使有 apps 配置也不会生效）
  const corps: CorpInfo[] | null = useMemo(() => {
    if (!appsCorps) return null
    return (
      apiConfigs
        .map(apiConfig => ({
          corpId: apiConfig.corpId,
          corpName: appsCorps.find(v => v.corpId === apiConfig.corpId)?.corpName ?? null,
        }))
        // 有 appsCorp 的排前面
        .sort((a, b) => (a.corpName !== null ? -1 : 1) - (b.corpName !== null ? -1 : 1))
    )
  }, [apiConfigs, appsCorps])

  return {
    corps,
    corpsLoading: loading,
    load,
    apiConfigs,
    appsCorps,
  }
}

/**
 * 添加、修改主体
 */
export interface EditCorp {
  corpId: string
  secret: string
  corpIdOrigin: string
  corpName: string
}
export async function saveCorp(
  values: EditCorp,
  prevCorpId: string | undefined,
  apiConfigs: QywxAPIConfig[],
  appsCorps: AppsCorpInfo[],
) {
  if (
    (prevCorpId === undefined || values.corpId !== prevCorpId) &&
    apiConfigs.find(v => v.corpId === values.corpId)
  ) {
    return failed('CorpId 已存在')
  }

  /*
  先保存 apps 数据，因为这个不一定成功；而 apiConfig 里是一定能成功的。
  保存有 apps 有四种情况：
  1. apps 里没有 prev.corpId 也没有 values.corpId 的主体 => 添加主体
  2. apps 里有 prev.corpId 的主体，没有 values.corpId 的主体 => 修改 prev.corpId 的主体
  3. apps 里没有 prev.corpId 的主体，但是有 values.corpId 的主体（之前的 corpId 在 apps 里没创建，但新改的 corpId 在 apps 里已存在）
       => 修改 values.corpId 主体
  4. apps 里既有 prev.corpId 的主体，又有 values.corpId 的主体（原企业和改后的企业在 apps 里都存在）
       => 修改 values.corpId 的主体
  */
  const hasPrevCorpId = !!(prevCorpId !== undefined && appsCorps.find(v => v.corpId === prevCorpId))
  const hasValuesCorpId = appsCorps.find(v => v.corpId === values.corpId)
  const appsRes = hasValuesCorpId
    ? await updateAppsCorp({ ...values, oldCorpId: values.corpId })
    : hasPrevCorpId
    ? await updateAppsCorp({ ...values, oldCorpId: prevCorpId })
    : await addAppsCorp(values)
  if (!appsRes.success) return failed(`主体保存失败 ${appsRes.error.code}:${appsRes.error.message}`)

  return updateApiConfig(values, prevCorpId)
}

/**
 * 维护选中的主体
 */
export function useChoosedCorpId(corps: CorpInfo[] | null) {
  const corpsRef = useRefValue(corps)
  const [corpId, rawSetCorpId] = useState<string | null>(null)
  const setCorpId = useCallback((corpId: string) => {
    rawSetCorpId(corpsRef.current?.find(v => v.corpId === corpId) ? corpId : null)
  }, [])

  const [inited, setInited] = useState(false)
  useEffect(() => {
    if (!inited) {
      if (corps !== null) {
        setInited(true)
        if (corps.length) setCorpId(corps[0]!.corpId)
      }
    } else {
      // 若列表里不再有当前 corpId，取消选中状态
      rawSetCorpId(corpId => ((corps ?? []).find(v => v.corpId === corpId) ? corpId : null))
    }
  }, [inited, corps])

  return { corpId, setCorpId }
}

/**
 * 维护主体详情
 */
export function useCorpDetail(
  corpId: string | null,
  corps: CorpInfo[] | null,
  apiConfigs: QywxAPIConfig[],
) {
  const [detail, setDetail] = useState<CorpDetail | null>(null)
  const [detailError, setDetailError] = useState('') // 详情加载失败时的错误信息
  const loadDetail = useCallback(async () => {
    setDetail(null)
    setDetailError('')
    if (corpId === null) return
    const corp = corps?.find(v => v.corpId === corpId)
    if (!corp) return
    const apiConfig = apiConfigs.find(v => v.corpId === corpId)!

    if (corp.corpName !== null) {
      const res = await getAppsCorpDetail(corpId)
      if (res.success) setDetail({ ...apiConfig, appsInfo: res.data })
      else setDetailError(res.error.message)
    } else {
      setDetail({ ...apiConfig, appsInfo: null })
    }
  }, [corpId, corps, apiConfigs])
  useEffect(() => void loadDetail(), [loadDetail])

  return { detail, detailError, loadDetail }
}
